#include <string.h>
#include <time.h>
// #include <sys/_timeval.h>

#include "hj212_client_def.h"
#include "hj212_client.h"
#include "hj212_msg.h"
#include "hj212_request.h"
#include "hj212_pack.h"
#include "hj212_data_stream.h"
#include "hj212_client_port.h"

#define HJ_LOG_TAG  "hj212.client"      // 日志标签
#define HJ_LOG_LVL HJ_DBG_LOG          // 日志等级
#include "hjdebug.h"

int hj212_free_sendbuf_isempty(hj212_client_t client)
{
    return rt_list_isempty(&client->idle_sendbuf_list);
}

// 从客户端获取一个发送缓冲区
struct send_buffer *hj212_acquire_sendbuf(hj212_client_t client)
{
    if (rt_list_isempty(&client->idle_sendbuf_list))
    {
        return NULL;
    }
    struct send_buffer *buffer = rt_list_entry(client->idle_sendbuf_list.next, struct send_buffer, list);
    rt_list_remove(&buffer->list);
    memset(buffer->mempool, 0, HJ212_PACK_MAX_SIZE);
    return buffer;
}

/* 将发送缓冲区，追加到发送链表(由客户端自动回收) */
void hj212_append_sendbuf(hj212_client_t client, struct send_buffer *buffer)
{
    rt_list_remove(&buffer->list);
    rt_list_insert_before(&client->sendbuf_list, &buffer->list);
}

/* 回收到不需要的空闲链表 */
void hj212_recycle_sendbuf(hj212_client_t client, struct send_buffer *buffer)
{
    rt_list_remove(&buffer->list);
    rt_list_insert_before(&client->idle_sendbuf_list, &buffer->list);
}

int hj212_datamsg_heartbeat(hj212_client_t client, int heartbeat)
{
    return hj212_send_local_pack(client, NULL, NULL, 8013, 0, NULL, "HeartbeatTime=%d;", (int)heartbeat);
}

/* 接收数据认领 */
int hj212_response_accept(struct hj212_client *client, struct hj212_generalmsg *msg, uint32_t package_state)
{
    int result = -1;
    struct hj212_response *response;
    rt_list_for_each_entry(response, &client->response_list, list)
    {
        if (response->match)    // 如果定义了match函数，直接使用该函数匹配
        {
            if (!response->match(response, msg, package_state, response->match_param))
            {
                result = 0;
                hj212_response_unregister(response);
                break;
            }
        }
        else    // 默认的匹配方法
        {
            if (package_state & ~UNPACK_NO_CP)  // 忽略CP字段，其他错误一概退出
            {
                continue;
            }
            if (msg->parent.cn != response->cn) // 比较CN
            {
                continue;
            }
            if (strncmp(msg->parent.qn, response->qn, HJ212_QN_MAX_LEN))    // 比较QN
            {
                continue;
            }
            if (!(package_state & UNPACK_NO_CP)) // 如有CP，则Copy该字段
            {
                strncpy(response->cp, msg->cp, HJ212_GENERAL_CP_MAX_LEN);
            }
            result = 0;
            hj212_response_unregister(response);
            break;
        }
    }
    return result;
}
/* 接收数据分发 */
void hj212_recv_msg_distribution(struct hj212_client *client, const char *recvbuf, int len)
{
    /* 处理可能出现的粘包 */
    const char *pos = recvbuf;
    while (pos != NULL)
    {
        /* 解包 */
        const char *p = NULL;
        memset(&client->recv_msg, 0,  sizeof(client->recv_msg));
        uint32_t package_state = hj212_unpack(pos, len, &client->recv_msg, UNPACK_NO_CHECK_CRC, &p); // 测试阶段先不校验CRC
        pos = p;
        if (package_state & (UNPACK_NO_HEAD | UNPACK_NO_END))   // 致命错误直接返回
        {
            continue;
        }
        /* hj212_response 认领消息 数据被正常认领后直接退出 */
        if (!hj212_response_accept(client, &client->recv_msg, package_state))
        {
            continue;
        }
        /* 未被认领的数据作为请求处理 */
        if (!(package_state & UNPACK_NO_QN))
        {
            if (hj212_request_parse(client, &client->recv_msg, package_state) < 0)
            {
                hj212_send_request_response(client, REQUEST_RESPONSE_REPULSE, client->recv_msg.parent.qn);
                continue;
            }
        }
#if 0   // QN错误暂时无处理
        else
        {
            // 上位机无QN是返回全0的QN
            hj212_send_request_response(client, REQUEST_RESPONSE_QN_ERROR, "00000000000000");
        }
#endif

    }
}
/* 响应控制块的超时处理 */
void hj212_response_timeout(struct hj212_client *client)
{
    time_t current = hj212_client_current_timestamp(client);
    struct hj212_response *response;
    rt_list_for_each_entry(response, &client->response_list, list)
    {
        if (current >= (response->register_time + response->timeout) && response->timeout_handle)
        {
            response->timeout_handle(response, response->timeout_param);
            break;
        }
    }
}

static struct timeval ms_format_timeval(struct timeval time, int ms_inter)
{
    int64_t timevalue = ((int64_t)time.tv_sec) * 1000 + time.tv_usec / 1000;
    timevalue = timevalue / ms_inter * ms_inter;
    struct timeval result;
    result.tv_sec = timevalue / 1000;
    result.tv_usec = (timevalue % 1000) * 1000;
#if 0
    HJ_LOG_D("time.tv_sec=%d, time.tv_usec=%d, timevalue=%ld, result.tv_sec=%d, result.tv_usec=%d",
             time.tv_sec, time.tv_usec, timevalue, result.tv_sec, result.tv_usec);
#endif
    return result;
}

void hj212_handle(struct hj212_client *client)
{
#if 0
    HJ_ASSERT(client != NULL);
    HJ_ASSERT(client->ops != NULL);
    HJ_ASSERT(client->ops->current_subsec != NULL);
#endif
    if (hj212_client_dev_state(client))
    {
        return;
    }
    struct timeval current = hj212_client_current_subsec(client);

    /* 逐条发送队列中的数据 */
    if (!rt_list_isempty(&client->sendbuf_list))
    {
        /* 时间差，毫秒 */
        int time_diff = (current.tv_sec -  client->last_send_time.tv_sec) * 1000 +
                        (current.tv_usec - client->last_send_time.tv_usec) / 1000;
        int send_inter = 50;
        hj212_client_command(client, GET_HJ212_SEND_INTER, &send_inter);
        if (time_diff >= send_inter)
        {
#if 0
            HJ_LOG_D("current.tv_sec=%d, client->last_send_time.tv_sec=%d, current.tv_usec=%d, client->last_send_time.tv_usec=%d, time_diff=%d, send_inter=%d",
                     current.tv_sec,
                     client->last_send_time.tv_sec,
                     current.tv_usec,
                     client->last_send_time.tv_usec,
                     time_diff,
                     send_inter);
#endif
            struct send_buffer *buffer = rt_list_entry(client->sendbuf_list.next, struct send_buffer, list);
            int len = strlen((char *)buffer->mempool);
            if (len > 0)
            {
                if (hj212_client_dev_send(client, (uint8_t *)buffer->mempool, len) == len)
                {
#if 1
                    HJ_LOGH_D((char *)buffer->mempool, len, "#%d hj212client send", client->id);
#endif
                    rt_list_remove(&buffer->list);
                    rt_list_insert_before(&client->idle_sendbuf_list, &buffer->list);
                }
            }
            client->last_send_time = ms_format_timeval(current, send_inter);
        }
        else if (time_diff < 0)
        {
            client->last_send_time = ms_format_timeval(current, send_inter);
        }
    }
    /* 必须发完所有数据再进行下面的处理(避免数据堵塞) */
    if (!rt_list_isempty(&client->sendbuf_list))
    {
        return;
    }

    /* 接收数据 - 分发到响应控制块 */
    int len = hj212_client_dev_recv(client, client->recv_buffer, HJ212_RECV_BUFFER_SIZE, 0);
    if (len > 0)
    {
#if 1
        HJ_LOGH_D(client->recv_buffer, len, "#%d hj212client recv", client->id);
#endif
        hj212_recv_msg_distribution(client, (char *)client->recv_buffer, len);
    }

    /* 处理超时的响应 */
    {
        hj212_response_timeout(client);
    }

    /* 执行请求 */
    {
        struct hj212_request *request, *tmp;
        // rt_list_for_each_entry(request, &client->request_list, list)
        rt_list_for_each_entry_safe(request, tmp, &client->request_list, list)
        {
            hj212_request_handle(client, request);
        }
    }

    /* 打包数据 */
    // if (hj212_free_sendbuf_isempty(client))    // 是否有空闲缓冲区
    {
        /* 更新数据流 */
        for (int i = 0; i < HJ212_MSG_TYPE_NUM; i++)
        {
            if ((client->push_enable & (1 << i)) && client->stream[i])
            {
                int stream_state = get_hj212_datastream_state(client->stream[i]);
                if (stream_state == HJ212_DATASTREAM_BUSY)
                {
                    break;
                }
                int maxret = 0;    // 不响应
                hj212_client_command(client, GET_HJ212_MAXRET, &maxret);
                if (hj212_datastream_push(client->stream[i], client, !!maxret) >= 0) // 只打包一条数据
                {
                    break;
                }
            }
        }

        /* 补足数据 */
        for (int i = 0; i < HJ212_MSG_TYPE_NUM; i++)
        {
            if (client->trigger_stream[i])
            {
                hj212_client_lock(client);
                int stream_state = get_hj212_datastream_state(client->trigger_stream[i]);
                if (stream_state == HJ212_DATASTREAM_BUSY)
                {
                    hj212_client_unlock(client);
                    break;
                }
                else if (stream_state == HJ212_DATASTREAM_EMPTY)
                {
                    HJ_LOG_I("#%d delete trigger_stream[%d] type(%d)", client->id, i, client->trigger_stream[i]->type);

                    hj212_client_delete_data_source(client, client->trigger_stream[i]->source);
                    hj212_datastream_delete(client, client->trigger_stream[i]);
                    client->trigger_stream[i] = NULL;
                    hj212_client_unlock(client);
                    continue;
                }
                int maxret = 0;    // 不响应
                hj212_client_command(client, GET_HJ212_MAXRET, &maxret);
                if (hj212_datastream_push(client->trigger_stream[i], client, !!maxret) >= 0) // 只打包一条数据
                {
                    hj212_client_unlock(client);
                    break;
                }
                hj212_client_unlock(client);
            }
        }
        /* 心跳包 */
        int heartbeat = 0;
        hj212_client_command(client, GET_HJ212_HEARTBEAT_CYCLE, &heartbeat);
        if (heartbeat != 0)
        {
            int heartbeat_time_diff = current.tv_sec - client->last_heartbeat_time;
            if (heartbeat_time_diff >= heartbeat)
            {
                hj212_datamsg_heartbeat(client, heartbeat);
                client->last_heartbeat_time = current.tv_sec / heartbeat * heartbeat;
            }
            else if (heartbeat_time_diff < 0) // 往回改了时间
            {
                client->last_heartbeat_time = current.tv_sec / heartbeat * heartbeat;
            }
        }
    }
}

int hj212_client_start(hj212_client_t client)
{
    hj212_client_lock(client);
    HJ_LOG_I("#%d hj212client start!", client->id);
    hj212_client_dev_open(client, 0);
    hj212_client_unlock(client);
    return 0;
}
int hj212_client_stop(hj212_client_t client)
{
    hj212_client_lock(client);
    HJ_LOG_I("#%d hj212client stop!", client->id);
    hj212_client_dev_close(client);
    hj212_client_unlock(client);
    return 0;
}
int hj212_client_updata_begin(hj212_client_t client, int type, time_t begin, time_t end, int mode)
{
    hj212_client_lock(client);

    if (!type)
        return -1;

    struct tm time_begin;
    struct tm time_end;
    localtime_r(&begin, &time_begin);
    localtime_r(&end, &time_end);

    HJ_LOG_I("#%d updata_begin type(%04x) begin(%04d/%02d/%02d %02d:%02d:%02d) end(%04d/%02d/%02d %02d:%02d:%02d)",
             client->id, type,
             time_begin.tm_year + 1900, time_begin.tm_mon + 1, time_begin.tm_mday,
             time_begin.tm_hour, time_begin.tm_min, time_begin.tm_sec,
             time_end.tm_year + 1900, time_end.tm_mon + 1, time_end.tm_mday,
             time_end.tm_hour, time_end.tm_min, time_end.tm_sec);

    for (int i = 0; i < HJ212_MSG_TYPE_NUM; i++)
    {
        if (client->trigger_stream[i])
        {
            HJ_LOG_I("#%d delete trigger_stream[%d] type(%d)", client->id, i, client->trigger_stream[i]->type);
            hj212_client_delete_data_source(client, client->trigger_stream[i]->source);
            hj212_datastream_delete(client, client->trigger_stream[i]);
            client->trigger_stream[i] = NULL;
        }
    }

    for (int i = 0; i < HJ212_MSG_TYPE_NUM; i++)
    {
        if (type | (1 << i))
        {
            struct hj212_datasource *source = hj212_client_create_hisdata_source(client, i, begin, end);
            if (source)
            {
                client->trigger_stream[i] = hj212_datastream_create(client, i, source);
                if (!client->trigger_stream[i])
                {
                    hj212_client_delete_data_source(client, source);
                }
            }
        }
    }

    hj212_client_unlock(client);

    return 0;
}

int hj212_client_pushstate(hj212_client_t client, int type, uint32_t enable)
{
    hj212_client_lock(client);
    if (enable)
    {
        client->push_enable |= (1 << type);
    }
    else
    {
        client->push_enable &= ~(1 << type);
    }
    HJ_LOG_I("#%d type%d %s", client->id, type, enable ? "enable" : "disable");
    hj212_client_unlock(client);
    return 0;
}

int get_hj212_client_pushstate(hj212_client_t client, int type)
{
    hj212_client_lock(client);
    int result = client->push_enable & (1 << type);
    hj212_client_unlock(client);
    return !!result;
}

void hj212_client_destroy(struct hj212_client *client)
{
    hj212_client_free(client, client->sendbuf);
    for (int i = 0; i < HJ212_MSG_TYPE_NUM; i++)
    {
        hj212_datastream_delete(client, client->stream[i]);
    }
}

int hj212_client_init(struct hj212_client *client, int id,
                      enum hj212_protocol_type protocol,
                      const struct hj212_client_ops *ops)
{
    HJ_ASSERT(ops && client);

    HJ_ASSERT(ops->command && ops->current_timestamp);
    HJ_ASSERT(ops->malloc && ops->calloc && ops->free);
    HJ_ASSERT(ops->dev_recv && ops->dev_send);

    int result = 0;

    memset(client, 0, sizeof(*client));
    client->id = id;
    client->ops = ops;

    client->last_send_time = (struct timeval)
    {
        0
    };

    client->sendbuf = hj212_client_malloc(client, sizeof(struct send_buffer) * HJ212_PACK_QUEUE_MAX_NUM);
    if (!client->sendbuf)
    {
        result = -1;
        goto __exit;
    }
    rt_list_init(&client->idle_sendbuf_list);
    rt_list_init(&client->sendbuf_list);
    for (int i = 0; i < HJ212_PACK_QUEUE_MAX_NUM; i++)
    {
        rt_list_insert_before(&client->idle_sendbuf_list, &client->sendbuf[i].list);
    }

    for (int i = 0; i < HJ212_MSG_TYPE_NUM; i++)
    {
        client->stream[i] = hj212_datastream_create(client, i, hj212_client_get_data_source(client, i));
        if (!client->stream[i])
        {
            result = -1;
            goto __exit;
        }
        client->push_enable |= (1 << i); // 暂时关闭主动上发功能
    }

    rt_list_init(&client->request_list);
    rt_list_init(&client->response_list);

    int heartbeat = 0;
    hj212_client_command(client, GET_HJ212_HEARTBEAT_CYCLE, &heartbeat);
    time_t current = hj212_client_current_timestamp(client);
    if (heartbeat == 0)
        heartbeat = 60;
    client->last_heartbeat_time = current / heartbeat * heartbeat;

    HJ_LOG_I("#%d hj212client create succeed!", client->id);

__exit:
    if (result < 0)
    {
        if (client->sendbuf)
            hj212_client_free(client, client->sendbuf);
        for (int i = 0; i < HJ212_MSG_TYPE_NUM; i++)
        {
            if (client->stream[i])
                hj212_datastream_delete(client, client->stream[i]);
            client->stream[i] = NULL;
        }
        HJ_LOG_W("#%d hj212client create failure", id);
    }
    return result;
}



